home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Libraries / ravlf 2.1 / ravlf.h < prev   
Encoding:
Text File  |  1995-07-24  |  19.3 KB  |  520 lines  |  [TEXT/KAHL]

  1. /*******************************************************************************
  2.  * ravlf.h
  3.  *
  4.  * Random-access, variable-length files
  5.  * C version 2.1, converted from Pascal to C April 1994, Modified July 1995
  6.  * By Tad Woods
  7.  * Postal mail: P.O. Box 1210, Salem, VA 24153
  8.  * CompuServe: 70312,3552   America Online: "Tad Woods"
  9.  * Internet         mail: tandtsw@roanoke.infi.net
  10.  *    anonymous ftp host: ftp.infi.net
  11.  *             directory: /pub/customer/roanoke/tandtsw
  12.  *
  13.  * Random-access, variable-length files (ravlf) implements direct access
  14.  * to variable-length records in a file's data fork.
  15.  *
  16.  * DISCLAIMER
  17.  * ----------
  18.  * You may compile this code (ravlf.c and ravlf.h) into your own 
  19.  * applications at no charge, as long as those applications are used
  20.  * in-house or distributed for free. To compile this code in shareware or
  21.  * commercial applications please contact the author for written permission.
  22.  * This software has been tested but comes with no guarantees or technical
  23.  * support. DO NOT SELL OR DISTRIBUTE THIS SOURCE CODE without the author's
  24.  * written permission.
  25.  *
  26.  * GENERAL INTERFACE
  27.  * -----------------
  28.  * The functionality is similar to, but simpler than, the Mac's Resource Manager.
  29.  * Call Init_Disk at the start of your program. Call Create_File to create
  30.  * a new ravlf. Call Open_File to open a ravlf once it has been created.
  31.  * Call Use_File to make a file the active ravlf, after it has been opened.
  32.  * Call Save_Data to store a handle's data in the active ravlf. Call
  33.  * Read_Data to read data from the active ravlf into a handle. Call
  34.  * Call Dispose_Data to delete a record. Call Close_File to close a ravlf.
  35.  * Call Dispose_Disk when your program Quits.
  36.  *
  37.  * RECORD KEYS
  38.  * -----------
  39.  * Records are identified by a key value, defined as a long by Key_Type,
  40.  * and may be any value in the valid range of a long, except -1 which
  41.  * is reserved for "record not found." You must provide a key value when
  42.  * calling Save_Data and Read_Data. You may generate the key value yourself
  43.  * or call Max_Key (and add 1) or Unique_Key to obtain a unique key value.
  44.  * Note that records must have unique keys. If you call Save_Data with a
  45.  * key value that already exists, the existing record will be deleted and
  46.  * replaced with the new data.
  47.  *
  48.  * MAXIMUM RECORD SIZE
  49.  * -------------------
  50.  * The maximum size of handle's data that can be saved, which is the same
  51.  * size of one ravlf record, is limited by the type of the pLength and 
  52.  * aLength fields of the dRecType typedef in "ravlf.c." They are currently
  53.  * defined as shorts, which limits the record size to 32K. If you need to
  54.  * store larger records change these two fields to long types. If you do
  55.  * this, files created under the old types will not be readable and may
  56.  * cause a crash if you try to read them.
  57.  *
  58.  * TIMESTAMP (optional parameter)
  59.  * ------------------------------
  60.  * Read_Data, Save_Data, and Dispose_Data also take a timestamp parameter.
  61.  * Save_Data and Dispose_Data will do nothing and return FALSE if the
  62.  * timestamp value does not match the timestamp value of the currently
  63.  * saved record with the same key value. Pass NULL for timestamp to ignore
  64.  * this check. (This can be used to prevent users from updating the same
  65.  * record at the same time in multi-user situations.)
  66.  *
  67.  * INDEXING (optional functions)
  68.  * --------------------------
  69.  * By default ravlf records are only indexed by their key values (described
  70.  * above). You may add one additional index in the form of a string, defined
  71.  * by Index_Type. Call Insert_Index to associate a string index with a key
  72.  * value (pass the key value as the id parameter). Call Find_Index to obtain
  73.  * the key value associated with a given string. Call Read_Next and 
  74.  * Read_Previous to obtain the id's of sequential indexed records. Pass -1
  75.  * to obtain the first or last indexed record id, respectively. Call 
  76.  * Delete_Index to remove an index. The case sensitivity of the indexing
  77.  * functions is determined by the indexCaseSensitive constant. By default,
  78.  * case is ignored (ravlf 2.0 was case sensitive). (Also note, the Find_Index 
  79.  * function now returns the element >= the search index.)
  80.  *
  81.  * INDEX LIMITATIONS
  82.  * -----------------
  83.  * One record can have only one index associated with it, and one index can
  84.  * have only one record associated with it. If you use the optional indexing,
  85.  * you should call Insert_Index just after calling Save_Data, and Delete_Index
  86.  * just after calling Dispose_Data. This is because deleting an index does
  87.  * not automatically delete an associated record, or deleting a record does
  88.  * not automatically delete an associated index.
  89.  *
  90.  * INDEX FIELD SIZE
  91.  * ----------------
  92.  * You may change the type of Index_Type in order to change its fixed length,
  93.  * but it must remain a pascal string. If you do change Index_Type, files
  94.  * created under the old type will not be readable and may cause a crash if
  95.  * you try to read them.
  96.  *
  97.  * SUB-RECORDS (PARENT & CHILD RECORDS)
  98.  * ------------------------------------
  99.  * You can add simple one-to-many (parent-to-child) relations between records.
  100.  * Call Relate to establish a relation. Call Get_Children to get a list of the
  101.  * child records related to a parent record. If you delete a child record, the 
  102.  * relationship is automatically removed from its parent record. If you delete
  103.  * a parent record, its children are automatically DELETED. (If you do not want
  104.  * a child deleted when a parent is deleted, call Remove_Parent_From_Child
  105.  * before you delete the parent.) A child can NOT have more than one parent;
  106.  * if you re-assign a child to a new parent the relationship with the original
  107.  * parent record is replaced. A record can be both a parent and a child.
  108.  * SUB-RECORD relationships are independent of the indexing functions.
  109.  *
  110.  * IMPORTANT NOTE: Files created with previous versions are not compatible
  111.  *                 with 2.1 because the size of some internal records changed.
  112.  *******************************************************************************/
  113.  
  114. #pragma once
  115.  
  116. #define Version            2
  117. #define NoID            -1L
  118. #define TimeStampError    -30500
  119. #define SubRecIntegrityError -30499
  120.  
  121. typedef long            Key_Type;
  122. typedef long            ID_Type;
  123. typedef Str63            Index_Type;
  124. typedef unsigned long    TimeStamp_Type;
  125. typedef Str32            User_Data;
  126. typedef struct {
  127.     ID_Type                id;
  128.     User_Data            user_data;
  129.     char                filler;
  130. } SubRec_Element_Type;
  131.  
  132.  
  133. /*******************************************************************************
  134.  * Init_Disk
  135.  *
  136.  * Call once at the start of your program before any other ravlf function.
  137.  *******************************************************************************/
  138. pascal void Init_Disk(void);
  139.  
  140.  
  141.  
  142. /*******************************************************************************
  143.  * Dispose_Disk
  144.  *
  145.  * Call once just before your program Quits.
  146.  *******************************************************************************/
  147. pascal void Dispose_Disk(void);
  148.  
  149.  
  150. /*******************************************************************************
  151.  * Disk_Error
  152.  *
  153.  * Returns an error code, or zero if no error occurred, from the last call to
  154.  * a ravlf function.
  155.  *******************************************************************************/
  156. pascal short Disk_Error(void);
  157.  
  158.  
  159.  
  160. /*******************************************************************************
  161.  * Cur_File
  162.  *
  163.  * Returns the file reference id of the currently active ravlf, or -1 if
  164.  * no file is active.
  165.  *******************************************************************************/
  166. pascal short Cur_File(void);
  167.  
  168.  
  169.  
  170. /*******************************************************************************
  171.  * Flush_Vol
  172.  *
  173.  *  -> volNum        volume reference number
  174.  *  -> async        TRUE to return from Flush_Vol immediately
  175.  *
  176.  * Flushes the volume referenced by volNum.
  177.  *******************************************************************************/
  178. pascal void Flush_Vol(short volNum, Boolean async);
  179.  
  180.  
  181.  
  182. /*******************************************************************************
  183.  * Use_File
  184.  *
  185.  *  -> newFileNum    ravlf file reference number (previously returned by
  186.  *                     Open_File)
  187.  *
  188.  * Makes newFileNum the active ravlf. Other ravlf functions operate on the
  189.  * active file.
  190.  *******************************************************************************/
  191. pascal void Use_File(short newFileNum);
  192.  
  193.  
  194.  
  195. /*******************************************************************************
  196.  * Open_File
  197.  *
  198.  *  -> volNum        volume reference number
  199.  *     -> dirID        directory id on volume (or zero if volNum is a working
  200.  *                    directory reference number)
  201.  *  -> name            name of file
  202.  *
  203.  * Opens a previously created file and makes it the active ravlf.
  204.  *******************************************************************************/
  205. pascal short Open_File(short volNum, long dirID, Str255 name);
  206.  
  207.  
  208.  
  209. /*******************************************************************************
  210.  * Close_File
  211.  *
  212.  *  -> closeFileNum        ravlf file reference number
  213.  *
  214.  * Closes a previously opened ravlf.
  215.  *******************************************************************************/
  216. pascal void Close_File(short closeFileNum);
  217.  
  218.  
  219.  
  220. /*******************************************************************************
  221.  * Create_File
  222.  *
  223.  *  -> volNum        volume reference number
  224.  *     -> dirID        directory id on volume (or zero if volNum is a working
  225.  *                    directory reference number)
  226.  *  -> name            name of file
  227.  *  -> creator        creator ID (application's signature)
  228.  *  -> fileType        file type (custom file type)
  229.  *  -> allowReplace    TRUE to allow the newly created file to replace an
  230.  *                    existing file of the same name
  231.  *
  232.  * Creates a ravlf.
  233.  *******************************************************************************/
  234. pascal void Create_File(short volNum, long dirID, Str255 name, OSType creator, OSType fileType, Boolean allowReplace);
  235.  
  236.  
  237.  
  238. /*******************************************************************************
  239.  * Remove_File
  240.  *
  241.  *  -> volNum        volume reference number
  242.  *     -> dirID        directory id on volume (or zero if volNum is a working
  243.  *                    directory reference number)
  244.  *  -> name            name of file
  245.  *
  246.  * Deletes a ravlf.
  247.  *******************************************************************************/
  248. pascal void Remove_File(short volNum, long dirID, Str255 name);
  249.  
  250.  
  251.  
  252. /*******************************************************************************
  253.  * Valid_Key
  254.  *
  255.  * <-> key        pointer to key value
  256.  *                on entry, key value to test
  257.  *                on exit, same value, next existing sequential key value, or -1
  258.  *
  259.  * Returns TRUE if a record exists for the value passed in key, or FALSE
  260.  * if it does not exist.
  261.  *******************************************************************************/
  262. pascal Boolean Valid_Key(Key_Type *key);
  263.  
  264.  
  265.  
  266. /*******************************************************************************
  267.  * Max_Key
  268.  *
  269.  * Returns the maxmium existing key value.
  270.  *******************************************************************************/
  271. pascal Key_Type Max_Key(void);
  272.  
  273.  
  274.  
  275. /*******************************************************************************
  276.  * Max_Key
  277.  *
  278.  * Returns the next non-existing, minimum, unique key value.
  279.  *******************************************************************************/
  280. pascal Key_Type Unique_Key(void);
  281.  
  282.  
  283.  
  284. /*******************************************************************************
  285.  * Dump_Tree
  286.  *
  287.  * An internal debugging function.
  288.  *******************************************************************************/
  289. #ifdef B_TREE_DEBUG
  290. pascal void Dump_Tree(void);
  291. #endif
  292.  
  293.  
  294.  
  295. /*******************************************************************************
  296.  * Read_TimeStamp
  297.  *
  298.  *  -> key        a key value
  299.  *
  300.  * Returns the timestamp value associated with the record associated with
  301.  * the key value.
  302.  *******************************************************************************/
  303. pascal TimeStamp_Type Read_TimeStamp(Key_Type key);
  304.  
  305.  
  306.  
  307. /*******************************************************************************
  308.  * Get_Children
  309.  *
  310.  *  -> id                a parent key value
  311.  *
  312.  * Returns a handle to a two-byte size element followed by size number of
  313.  * SubRec_Element_Type elements that describe children records.
  314.  *******************************************************************************/
  315. pascal Handle Get_Children(Key_Type key);
  316.  
  317.  
  318.  
  319. /*******************************************************************************
  320.  * Has_Children
  321.  *
  322.  *  -> id                a parent key value
  323.  *
  324.  * Returns TRUE if the parent record id has children records related to it.
  325.  *******************************************************************************/
  326. pascal Boolean Has_Children(Key_Type key);
  327.  
  328.  
  329.  
  330. /*******************************************************************************
  331.  * Get_Parent
  332.  *
  333.  *  -> id                a child key value
  334.  *
  335.  * Returns the key value of child record id's parent or -1 if no parent.
  336.  *******************************************************************************/
  337. pascal Key_Type Get_Parent(Key_Type key);
  338.  
  339.  
  340.  
  341. /*******************************************************************************
  342.  * Remove_Parent_From_Child
  343.  *
  344.  *  -> id                a child key value
  345.  *
  346.  * Removes the relationship between the child record id and its parent
  347.  * record. No records are deleted. (Called by Dispose_Data.)
  348.  *******************************************************************************/
  349. pascal void Remove_Parent_From_Child(Key_Type key);
  350.  
  351.  
  352. /*******************************************************************************
  353.  * Dispose_Children
  354.  *
  355.  *  -> id                a parent key value
  356.  *
  357.  * Disposes of all the records that are children of parent record id.
  358.  * The parent record itself is not deleted. (Called by Dispose_Data.)
  359.  *******************************************************************************/
  360. pascal void Dispose_Children(Key_Type key);
  361.  
  362.  
  363.  
  364. /*******************************************************************************
  365.  * Relate
  366.  *
  367.  *  -> parent            a parent key value
  368.  *  -> child            a child key value
  369.  *  -> user_data        user data
  370.  *  -> before            element to insert before in list of children for
  371.  *                        ordering purposes (elements are numbered 0..n-1,
  372.  *                        pass -1 to insert at end)
  373.  *
  374.  * Returns TRUE if relationship is made, FALSE if a record was not found
  375.  * or an error occurred.
  376.  * Relates the parent record to the child record.
  377.  *******************************************************************************/
  378. pascal Boolean Relate(Key_Type parent, Key_Type child, User_Data user_data, short before);
  379.  
  380.  
  381.  
  382. /*******************************************************************************
  383.  * Dispose_Data
  384.  *
  385.  *  -> key                a key value
  386.  *  -> old_timestamp    pointer to a timestamp value, or NULL to ignore
  387.  *                        on entry, timestamp value returned from previous
  388.  *                                  Read_Data or Save_Data call
  389.  *
  390.  * Returns TRUE if the record associated with key was deleted.
  391.  * Returns FALSE and does nothing if old_timestamp ≠ NULL, and old_timestamp
  392.  * references a non-zero value, and old_timestamp does not match the timestamp
  393.  * value now associated with the record associated with key.
  394.  *******************************************************************************/
  395. pascal Boolean Dispose_Data(Key_Type key, TimeStamp_Type *old_timestamp);
  396.  
  397.  
  398.  
  399. /*******************************************************************************
  400.  * Save_Data
  401.  *
  402.  *  -> key                a key value
  403.  *  -> data                a valid Macintosh Handle to data to save
  404.  * <-> old_timestamp    pointer to a timestamp value, or NULL to ignore
  405.  *                        on entry, timestamp value returned from previous
  406.  *                                  Read_Data or Save_Data call
  407.  *                        on exit, timestamp value for newly saved record
  408.  *
  409.  * Returns TRUE if the record associated with key was saved.
  410.  * Returns FALSE and does nothing if old_timestamp ≠ NULL, and old_timestamp
  411.  * references a non-zero value, and old_timestamp does not match the timestamp
  412.  * value now associated with the record associated with key.
  413.  * NOTES: data will be unlocked on exit. data must be valid, but if it is
  414.  * zero length no record will be saved and Dispose_Data will be called for
  415.  * the record associated with key instead.
  416.  *******************************************************************************/
  417. pascal Boolean Save_Data(Key_Type key, Handle data, TimeStamp_Type *old_timestamp);
  418.  
  419.  
  420.  
  421. /*******************************************************************************
  422.  * Read_Data
  423.  *
  424.  *  -> key                a key value
  425.  * <-  timestamp        pointer to a timestamp value, or NULL to ignore
  426.  *                        on exit, timestamp value for record read
  427.  *
  428.  * Returns a newly allocate Handle for the record associated with key,
  429.  * or NULL if no record was found. It is up to the calling program to
  430.  * call DisposHandle when it is ready to dispose of this new Handle.
  431.  * If Read_Data returns NULL and Disk_Error returns noErr, then no record
  432.  * existed for key.
  433.  *******************************************************************************/
  434. pascal Handle Read_Data(Key_Type key, TimeStamp_Type *timestamp);
  435.  
  436.  
  437.  
  438. /*******************************************************************************
  439.  * Read_Index
  440.  *
  441.  *  -> id                a key value, or -1 to get the id of first item in
  442.  *                        the index
  443.  *
  444.  * Returns id if an index exists for the id, or -1 if no index exists for id.
  445.  *******************************************************************************/
  446. pascal ID_Type Read_Index(ID_Type id);
  447.  
  448.  
  449.  
  450. /*******************************************************************************
  451.  * Read_Next
  452.  *
  453.  *  -> current_id        a key value, or -1 to get the id of first item in
  454.  *                        the index
  455.  *
  456.  * Returns the id of the item that is sequentially after current_id in the
  457.  * index, or -1 if there are no more items.
  458.  *******************************************************************************/
  459. pascal ID_Type Read_Next(ID_Type current_id);
  460.  
  461.  
  462.  
  463. /*******************************************************************************
  464.  * Read_Previous
  465.  *
  466.  *  -> current_id        a key value, or -1 to get the id of last item in
  467.  *                        the index
  468.  *
  469.  * Returns the id of the item that is sequentially before current_id in the
  470.  * index, or -1 if there are no more items.
  471.  *******************************************************************************/
  472. pascal ID_Type Read_Previous(ID_Type current_id);
  473.  
  474.  
  475.  
  476. /*******************************************************************************
  477.  * Insert_Index
  478.  *
  479.  *  -> index            an index value to associate with the record associated
  480.  *                        with id
  481.  *  -> id                a key value
  482.  *
  483.  * Adds an index item for id.
  484.  *******************************************************************************/
  485. pascal void Insert_Index(Index_Type index, ID_Type id);
  486.  
  487.  
  488.  
  489. /*******************************************************************************
  490.  * Delete_Index
  491.  *
  492.  *  -> id                a key value
  493.  *
  494.  * Deletes the index item associated with id.
  495.  *******************************************************************************/
  496. pascal void Delete_Index(ID_Type id);
  497.  
  498.  
  499.  
  500. /*******************************************************************************
  501.  * Find_Index
  502.  *
  503.  *  -> index            an index value to search for
  504.  *  -> id                a key value of item to start search on, or -1 to
  505.  *                        search from the first item in the index
  506.  *
  507.  * Returns the id of the first item (the key value) that is equal to or
  508.  * greater than the index.
  509.  *******************************************************************************/
  510. pascal ID_Type Find_Index(Index_Type index, ID_Type id);
  511.  
  512.  
  513.  
  514. /*******************************************************************************
  515.  * Count_Index
  516.  *
  517.  * Returns a count of the number of indexed items. If you Insert_Index for
  518.  * each record you Save_Data, this will also be the record count.
  519.  *******************************************************************************/
  520. pascal long Count_Index(void);